/**
 * WebSocket 服务模块
 * 提供实时通信功能
 */

const WebSocket = require('ws');

class WebSocketService {
    constructor(server) {
        this.wss = new WebSocket.Server({
            server,
            path: '/ws', // WebSocket 连接路径
        });
        this.clients = new Map(); // 存储客户端连接
        this.messageHandlers = new Map(); // 存储消息处理器

        this.init();
    }

    /**
     * 初始化 WebSocket 服务
     */
    init() {
        this.wss.on('connection', (ws, req) => {
            const clientId = this.generateClientId();
            const clientInfo = {
                id: clientId,
                ws: ws,
                ip: req.socket.remoteAddress,
                connectTime: new Date(),
                isAlive: true,
            };

            this.clients.set(clientId, clientInfo);
            console.log(`[WebSocket] 客户端连接: ${clientId} (IP: ${clientInfo.ip})`);

            // 发送欢迎消息
            this.sendToClient(clientId, {
                type: 'welcome',
                message: '连接成功',
                clientId: clientId,
                timestamp: new Date().toISOString(),
            });

            // 处理客户端消息
            ws.on('message', (data) => {
                try {
                    const message = JSON.parse(data.toString());
                    console.log(data.toString(), '------message');
                    this.handleMessage(clientId, message);
                } catch (error) {
                    console.error(`[WebSocket] 消息解析错误:`, error);
                    this.sendToClient(clientId, {
                        type: 'error',
                        message: '消息格式错误',
                        timestamp: new Date().toISOString(),
                    });
                }
            });

            // 处理连接关闭
            ws.on('close', (code, reason) => {
                console.log(`[WebSocket] 客户端断开: ${clientId} (代码: ${code}, 原因: ${reason})`);
                this.clients.delete(clientId);
            });

            // 处理连接错误
            ws.on('error', (error) => {
                console.error(`[WebSocket] 客户端错误: ${clientId}`, error);
                this.clients.delete(clientId);
            });

            // 心跳检测
            ws.on('pong', () => {
                const client = this.clients.get(clientId);
                if (client) {
                    client.isAlive = true;
                }
            });
        });

        // 定期心跳检测
        this.startHeartbeat();
    }

    /**
     * 生成客户端ID
     */
    generateClientId() {
        return `client_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }

    /**
     * 处理客户端消息
     */
    handleMessage(clientId, message) {
        const client = this.clients.get(clientId);
        if (!client) return;

        console.log(`[WebSocket] 收到消息 [${clientId}]:`, message);

        switch (message.type) {
            case 'ping':
                this.sendToClient(clientId, {
                    type: 'pong',
                    timestamp: new Date().toISOString(),
                });
                break;

            case 'broadcast':
                this.broadcast(message.data, clientId);
                break;

            case 'private':
                if (message.targetClientId) {
                    this.sendToClient(message.targetClientId, {
                        type: 'private',
                        from: clientId,
                        data: message.data,
                        timestamp: new Date().toISOString(),
                    });
                }
                break;

            case 'getClients':
                this.sendToClient(clientId, {
                    type: 'clients',
                    data: Array.from(this.clients.keys()),
                    timestamp: new Date().toISOString(),
                });
                break;

            default:
                // 调用自定义消息处理器
                const handler = this.messageHandlers.get(message.type);
                if (handler) {
                    handler(clientId, message, this);
                } else {
                    this.sendToClient(clientId, {
                        type: 'error',
                        message: `未知消息类型: ${message.type}`,
                        timestamp: new Date().toISOString(),
                    });
                }
        }
    }

    /**
     * 发送消息给指定客户端
     */
    sendToClient(clientId, message) {
        const client = this.clients.get(clientId);
        if (client && client.ws.readyState === WebSocket.OPEN) {
            try {
                client.ws.send(JSON.stringify(message));
                return true;
            } catch (error) {
                console.error(`[WebSocket] 发送消息失败 [${clientId}]:`, error);
                return false;
            }
        }
        return false;
    }

    /**
     * 广播消息给所有客户端
     */
    broadcast(message, excludeClientId = null) {
        const data = {
            type: 'broadcast',
            data: message,
            timestamp: new Date().toISOString(),
        };

        this.clients.forEach((client, clientId) => {
            if (clientId !== excludeClientId) {
                this.sendToClient(clientId, data);
            }
        });

        console.log(`[WebSocket] 广播消息给 ${this.clients.size} 个客户端`);
    }

    /**
     * 获取在线客户端数量
     */
    getClientCount() {
        return this.clients.size;
    }

    /**
     * 获取所有客户端信息
     */
    getClients() {
        return Array.from(this.clients.values()).map((client) => ({
            id: client.id,
            ip: client.ip,
            connectTime: client.connectTime,
            isAlive: client.isAlive,
        }));
    }

    /**
     * 注册自定义消息处理器
     */
    registerHandler(messageType, handler) {
        this.messageHandlers.set(messageType, handler);
    }

    /**
     * 启动心跳检测
     */
    startHeartbeat() {
        const interval = setInterval(() => {
            this.clients.forEach((client, clientId) => {
                if (!client.isAlive) {
                    console.log(`[WebSocket] 客户端心跳超时: ${clientId}`);
                    client.ws.terminate();
                    this.clients.delete(clientId);
                    return;
                }

                client.isAlive = false;
                client.ws.ping();
            });
        }, 30000); // 30秒心跳检测

        this.wss.on('close', () => {
            clearInterval(interval);
        });
    }

    /**
     * 关闭 WebSocket 服务
     */
    close() {
        this.wss.close();
        console.log('[WebSocket] 服务已关闭');
    }
}

module.exports = WebSocketService;
